#include "preprocessor.hpp"
#include <iostream>
#define LINE_CONTINUATION ':'
using namespace std;

enum {
	PRE_PAREN=0,
	PRE_BRACE,
	PRE_BRACKET
};

string preprocess(string full,std::istream& source)
{
	UNUSED source;
	vector<int> counter(0);
	string str="";
	bool flag=false;
	while(full.size()) {
		while(full.size()) {
			flag=false;
			if(full[0]==';') {
				str += full[0];
				full = full.substr(1);
				flag=true;
			} else if(full[0]=='{') {
				counter.push_back(PRE_BRACE);
				str += full[0];
				full = full.substr(1);
			} else if(full[0]=='(') {
				counter.push_back(PRE_PAREN);
				str += full[0];
				full = full.substr(1);
			} else if(full[0]=='[') {
				counter.push_back(PRE_BRACKET);
				str += full[0];
				full = full.substr(1);
			} else if(full[0]=='}') {
				if(counter.size()) {
					if(counter.back()!=PRE_BRACE) {
						_throw_error(ERROR_MISMATCHBRACKETS);
						return "null";
					} else {
						counter.pop_back();
					}
				} else {
					_throw_error(ERROR_MISMATCHBRACKETS);
					return str;
				}
				str += full[0];
				full = full.substr(1);
			} else if(full[0]==')') {
				if(counter.size()) {
					if(counter.back()!=PRE_PAREN) {
						_throw_error(ERROR_MISMATCHBRACKETS);
						return "null";
					} else {
						counter.pop_back();
					}
				} else {
					_throw_error(ERROR_MISMATCHBRACKETS);
					return str;
				}
				str += full[0];
				full = full.substr(1);
			} else if(full[0]==']') {
				if(counter.size()) {
					if(counter.back()!=PRE_BRACKET) {
						_throw_error(ERROR_MISMATCHBRACKETS);
						return "null";
					} else {
						counter.pop_back();
					}
				} else {
					_throw_error(ERROR_MISMATCHBRACKETS);
					return str;
				}
				str += full[0];
				full = full.substr(1);
			} else if( (full[0]=='`')||(full[0]=='\'')||(full[0]=='\"') ) {
				unsigned i;
				str += full[0];
				for(i=1;i<full.size();i++) {
					if(full[i]=='\\') {
						str += '\\';
						if(i+1 != full.size()) {
							if(full[i+1]==full[0]) {
								i++;
								str += full[0];
							}
						}
					} else if(full[i]==full[0]) {
						str += full[0];
						break;
					} else {
						str += full[i];
					}
				}
				if(i!=full.size()) {
					full = full.substr(i+1);
				} else {
					full.clear();
				}
			} else if(full[0]=='#') {
				// Comment
				full.clear();
			} else {
				str += full[0];
				full = full.substr(1);
			}
		}
		if(counter.size() || str[str.size()-1] == LINE_CONTINUATION) {
			if(str[str.size()-1] == LINE_CONTINUATION) {
				// The user put in a manual line continuation
				str = str.substr(0,str.size()-1);
			}
			// Mismatched brackets or parenthesis
			// We know that it's positive because it would have been caught earlier
			#if CURRENT_OS == OS_linux
				if(full[full.size()-1]=='\r') {
					full = full.substr(0,full.size()-1);
				}
			#endif
			string buffer = "";
			do {
				if(source==std::cin) {
					cout << "...\t";
				}
				getline(source,buffer);
			}while(buffer.empty());
			#if CURRENT_OS == OS_linux
				if(buffer[buffer.size()-1]=='\r') {
					buffer = buffer.substr(0,buffer.size()-1);
				}
			#endif
			while( buffer[0]==' ' ||
				buffer[0]=='\t' ||
				buffer[0]=='\n' ||
				buffer[0]=='\0'
			) {
				buffer = buffer.substr(1,buffer.size()-1);
			}
			full += ' ' + buffer;
			if(flag) {
				char ch = full.at(full.find_first_not_of(" \t\n"));
				if(!(islegalvarnamestarter(ch) || isspecialchar(ch) || isopcode(ch))) {
					full.insert(0,"null");
				}
			}
		}
	}
	return str;
}
